package com.diaohw.platform.utility.uml.service;

import com.diaohw.platform.common.util.ClassUtils;
import com.diaohw.platform.utility.uml.obj.ClassTreeBO;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Stream;

@Service
public class UMLProcessService {

    public List<ClassTreeBO> load() {

        List<String> classes = ClassUtils.scanPackage().stream()
                .filter(c -> c.isAnnotationPresent(SpringBootApplication.class))
                .map(clazz -> {
                    boolean present = clazz.isAnnotationPresent(ComponentScan.class);
                    if (present) {
                        ComponentScan scan = clazz.getAnnotation(ComponentScan.class);
                        List<String> list = Arrays.stream(scan.basePackageClasses()).map(Class::getPackageName).toList();
                        String[] strings = scan.basePackages();
                        List<String> pk = new ArrayList<>();
                        pk.addAll(list);
                        pk.addAll(List.of(strings));
                        return pk;
                    }

                    return List.of(clazz.getPackageName());
                })
                .flatMap((Function<List<String>, Stream<String>>) Collection::stream)
                .map(ClassUtils::scanPackage)
                .flatMap(Set::stream)
                .map(Class::getName)
                .toList();

        List<ClassTreeBO> trees = new ArrayList<>();
        Map<String, ClassTreeBO> treeMap = new HashMap<>();

        for (String str : classes) {

            String[] split = str.split("\\.");
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < split.length; i++) {
                String parent = sb.toString();
                if (i > 0) {
                    sb.append(".");
                }
                sb.append(split[i]);
                String nodeId = sb.toString();
                if (treeMap.containsKey(nodeId)) {
                    continue;
                }
                ClassTreeBO tree = new ClassTreeBO(nodeId, split[i], parent);
                treeMap.put(nodeId, tree);
                if (treeMap.containsKey(parent)) {
                    treeMap.get(parent).getChildren().add(tree);
                    continue;
                }

                treeMap.get(nodeId).setParent("0");
                trees.add(tree);
            }
            treeMap.get(str).setChildren(null);
        }
        while (true) {
            if (trees.size() == 1) {
                trees = trees.get(0).getChildren();
                continue;
            }
            break;
        }
        return trees;
    }
}
